<template>
    <el-card class="box-card">
        <template #header>
            <el-row>
                <el-button type="primary" :icon="Plus" @click="handleAdd">添加角色</el-button>
                <el-button type="danger" :icon="Delete" @click="handleBatchDelete">批量删除</el-button>
            </el-row>
        </template>

        <el-table ref="tableRef" :data="state.tableData" :empty-text="state.empty">
            <el-table-column type="selection" width="38" />
            <el-table-column prop="name" label="角色标识" show-overflow-tooltip />
            <el-table-column prop="title" label="角色名称" show-overflow-tooltip />
            <el-table-column prop="menu" label="菜单权限" align="center">
                <template #default="scope">
                    <el-button type="primary" text @click="handleMenu(scope.row)">设置权限</el-button>
                </template>
            </el-table-column>

            <el-table-column prop="action" label="操作权限" align="center">
                <template #default="scope">
                    <el-button type="primary" text @click="handleAction(scope.row)">设置权限</el-button>
                </template>
            </el-table-column>
            <el-table-column prop="role" label="角色列表" width="200">
                <template #default="scope">
                    <span class="permission">
                        <el-tag v-for="item in scope.row.permission" :key="item.id">
                            {{ item.title }}
                        </el-tag>
                    </span>
                </template>
            </el-table-column>
            <el-table-column fixed="right" label="状态" align="center" width="54">
                <template #default="scope">
                    <el-switch v-model="scope.row.status" :active-value="0" :inactive-value="1"
                        @change="changeStatus(scope.row)" size="small" />
                </template>
            </el-table-column>
            <el-table-column fixed="right" label="操作" width="96" align="center">
                <template #default="scope">
                    <el-button link type="primary" @click="handleEdit(scope.row)" size="small">编辑</el-button>
                    <el-popconfirm title="确定要删除吗？" @confirm="handleDelete(scope.row.id)">
                        <template #reference>
                            <el-button link type="primary" size="small">删除</el-button>
                        </template>
                    </el-popconfirm>
                </template>
            </el-table-column>
        </el-table>

        <el-dialog v-model="state.handleDialog" width="400px">
            <template #header>
                {{ isEdit ? '编辑账户' : '添加账户' }}
            </template>
            <el-form ref="ruleForm" :model="state.form" :rules="rules" status-icon>

                <el-form-item label="角色标识" prop="name">
                    <el-input v-model="state.form.name" placeholder="输入标识"
                        :formatter="(value) => `${value}`.toLocaleUpperCase()" />
                </el-form-item>
                <el-form-item label="角色名称" prop="title">
                    <el-input v-model="state.form.title" placeholder="输入名称" />
                </el-form-item>

                <el-form-item label="角色列表" prop="role">
                    <el-checkbox-group v-model="state.form.role">
                        <el-checkbox v-for="item in state.tableData" :label="item.id" :key="item.id">{{ item.title
                        }}</el-checkbox>
                    </el-checkbox-group>
                </el-form-item>

                <el-form-item label="角色状态" prop="status">
                    <el-radio-group v-model="state.form.status">
                        <el-radio :label="0">启用</el-radio>
                        <el-radio :label="1">停用</el-radio>
                    </el-radio-group>
                </el-form-item>

            </el-form>

            <template #footer>
                <div class="dialog-footer">
                    <el-button @click="state.handleDialog = false">取消</el-button>
                    <el-button type="primary" @click="submitForm">确认</el-button>
                </div>
            </template>
        </el-dialog>

        <el-dialog v-model="state.handleMenuDialog" width="400px">
            <template #header>
                菜单权限
            </template>
            <el-scrollbar height="320px">
                <el-tree ref="menuTree" :data="state.menuData" show-checkbox node-key="id"
                    :props="{ children: 'children', label: 'title' }" default-expand-all />
            </el-scrollbar>
            <template #footer>
                <div class="dialog-footer">
                    <el-button @click="state.handleMenuDialog = false">取消</el-button>
                    <el-button type="primary" @click="submitChange('menu')">确认</el-button>
                </div>
            </template>
        </el-dialog>

        <el-dialog v-model="state.handleActionDialog" width="600px">
            <template #header>
                操作权限
            </template>
            <el-scrollbar height="320px">
                <el-tree ref="actionTree" :data="state.actionData" node-key="id" show-checkbox
                    :props="{ class: customNodeClass }" default-expand-all>
                </el-tree>
            </el-scrollbar>
            <template #footer>
                <div class="dialog-footer">
                    <el-button @click="state.handleActionDialog = false">取消</el-button>
                    <el-button type="primary" @click="submitChange('action')">确认</el-button>
                </div>
            </template>
        </el-dialog>
    </el-card>
</template>
<script setup>
import { ref, reactive, nextTick } from 'vue'
import { Plus, Delete } from '@element-plus/icons-vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import Request from '@/request'

const ruleForm = ref()
const menuTree = ref()
const actionTree = ref()
const tableRef = ref()


const defaultForm = {
    name: '',
    title: '',
    role: [],
    status: 0
}

const state = reactive({
    tableData: [],
    menuData: [],
    actionData: [],
    handleDialog: false,
    handleMenuDialog: false,
    handleActionDialog: false,
    isEdit: false,
    id: '',
    empty: '暂无数据',
    form: JSON.parse(JSON.stringify(defaultForm))
})

const rules = {
    name: [
        { required: true, message: '请输入角色标识！', trigger: ['blur'] },
        { min: 3, message: '长度不能低于3位！', trigger: ['blur'] }
    ],
    title: [
        { required: true, message: '请输入角色名称！', trigger: ['blur'] },
        { min: 3, message: '长度不能低于3位！', trigger: ['blur'] }
    ],
    role: [
        { required: true, message: '请勾选显示角色列表！', trigger: ['blur'] }
    ],
    status: [
        { required: true, message: '请选择状态！', trigger: ['blur'] }
    ]
}

const handleBatchDelete = () => {
    nextTick(() => {
        const selection = tableRef.value.getSelectionRows()
        const ids = selection.map(item => item.id)
        if (ids.length) {
            ElMessageBox.confirm(
                '确定要批量删除吗？',
                '提示',
                {
                    confirmButtonText: '确定',
                    cancelButtonText: '取消',
                    type: 'warning'
                }
            ).then(() => {
                handleDelete(ids)
            }).catch(() => {

            })

        } else {
            ElMessage({
                message: '请先选中一个！',
                grouping: true,
                type: 'warning'
            })
        }
    })
}

const handleAdd = () => {
    state.isEdit = false
    state.handleDialog = true
    state.form = JSON.parse(JSON.stringify(defaultForm))
}

const handleEdit = (row) => {
    state.isEdit = true
    state.handleDialog = true
    state.form = JSON.parse(JSON.stringify(row))
    state.form.role = JSON.parse(row.role)
}

const handleDelete = (id) => {
    Request
        .post('system/role/delete', { id: id })
        .then(res => {
            if (!res.code) {
                getDataList()
            }

            ElMessage({
                message: res.message,
                type: res.code ? 'error' : 'success'
            })
        })
        .catch((error) => {
            console.log('error', error)
        })
}

const changeStatus = (row) => {
    Request
        .post('system/role/field', { id: row.id, field: 'status', value: row.status ? 1 : 0 })
        .then(res => {
            getDataList()
            ElMessage({
                message: res.message,
                grouping: true,
                type: res.code ? 'error' : 'success'
            })
        })
        .catch((error) => {
            console.log('error', error)
        })
}

const handleMenu = (row) => {
    state.id = row.id
    Request
        .get('system/menu/index')
        .then(res => {
            if (res.code) {
                ElMessage.error(res.message)
            } else {
                state.menuData = res.datas
                state.handleMenuDialog = true
                nextTick(() => {
                    menuTree.value.setCheckedKeys([])
                    menuTree.value.setCheckedKeys(JSON.parse(row.menu))
                })
            }
        })
        .catch((error) => {
            console.log('error', error)
        })
}

const handleAction = (row) => {
    state.id = row.id
    Request
        .get('system/role/rule')
        .then(res => {
            if (res.code) {
                ElMessage.error(res.message)
            } else {
                state.actionData = res.datas
                state.handleActionDialog = true
                nextTick(() => {
                    actionTree.value.setCheckedKeys([])
                    actionTree.value.setCheckedKeys(JSON.parse(row.action))
                })
            }
        })
        .catch((error) => {
            console.log('error', error)
        })
}

const submitChange = (field) => {
    let value
    if (field == 'menu') {
        value = menuTree.value.getCheckedKeys()
    } else {
        value = actionTree.value.getCheckedKeys(true)
    }

    Request
        .post('system/role/field', { id: state.id, field: field, value: JSON.stringify(value) })
        .then(res => {
            if (!res.code) {
                getDataList()
                state.handleMenuDialog = false
                state.handleActionDialog = false
            }

            ElMessage({
                message: res.message,
                type: res.code ? 'error' : 'success'
            })
        })
        .catch((error) => {
            console.log('error', error)
        })
}

const submitForm = () => {
    if (!ruleForm) return
    ruleForm.value.validate(valid => {
        if (valid) {
            const url = state.isEdit ? 'system/role/edit' : 'system/role/add'
            Request
                .post(url, state.form)
                .then(res => {
                    if (!res.code) {
                        getDataList()
                        state.handleDialog = false
                    }

                    ElMessage({
                        message: res.message,
                        type: res.code ? 'error' : 'success'
                    })
                })
                .catch((error) => {
                    console.log('error', error)
                })
        }
    })
}

const getDataList = () => {
    Request
        .post('system/role/index')
        .then(res => {
            if (res.code) {
                state.empty = res.message
            } else {
                state.tableData = res.datas.data
            }
        })
        .catch((error) => {
            console.log('error', error)
        })
}

getDataList()

const customNodeClass = (data, node) => {
    if (data.isOne) {
        return 'isOne'
    }

    if (data.isTwo) {
        return 'isTwo'
    }
    return null
}
</script>
<style>
.isOne>.el-tree-node__content {
    text-transform: capitalize;
    color: #409EFF;
}

.isTwo>.el-tree-node__content {
    color: #79bbff;
    text-transform: capitalize;
}

.el-tree-node.is-expanded.isTwo>.el-tree-node__children {
    display: flex;
    flex-direction: row;
    flex-wrap: wrap;
}

.isTwo>.el-tree-node__children>div {
    width: 25%;
}

.permission .el-tag {
    margin-right: 10px;
}
</style>